<?php
/**
 * A blueprint for every element in the form class-structure.
 *
 * @author Niels Janssen
 * @since 2008-07-08
 * @package Form
 */
abstract class FormNode {

	/**
	 * Whether or not an error (during validation) has occured in this element.
	 *
	 * @var boolean
	 */
	protected $errorFound = false;

	/**
	 * The error message.
	 *
	 * @var String
	 */
	protected $errorMessage = '';

	/**
	 * The parent of this node.
	 *
	 * @var FormNode
	 */
	protected $parent = null;

	/**
	 * The name of the node.
	 *
	 * @var String
	 */
	protected $name = '';

	/**
	 * The ID of the node.
	 *
	 * @var String
	 */
	protected $id = '';

	/**
	 * The value of the node.
	 */
	protected $value = '';

	/**
	 * Extra properties.
	 *
	 * @var array
	 */
	protected $properties = array();

	/**
	 * @var ElementValidation
	 */
	protected $validator = null;

	/**
	 *
	 */
	function __construct( $name, array $properties = array() ) {
		$this->name = $name;
		$this->setProperties( $properties );
	}

	public function getProperty( $key ) {
		return isset( $this->properties[ $key ] ) ? $this->properties[ $key ] : 
			( isset($this->$key) && !empty( $this->$key ) ? $this->$key : null );
	}

	public function setProperties( array $properties ) {
		if( !( count( $properties ) > 0 ) ) return;

		foreach( $properties as $key => $value ) {
			switch ( $key ) {
				case 'name' :
					$this->name = $value;
					break;

				case 'value' :
					$this->value = $value;
					break;
			}
			$this->properties[ $key ] = $value;
		}
	}

	public function setProperty( $key, $value ) {
		$this->setProperties( array(
			$key => $value
		) );
	}

	/**
	 * Sets the parent of a node, but does not allow a form to get a parent.
	 *
	 * @param FormNode $parent
	 */
	public function setParent( $parent ) {
		if( $this instanceof Form ) {
			throw new FormException( "A form cannot have a parent" );
		}
		
		$this->parent = $parent;
	}
	
	/**
	 * Gets the parent
	 *
	 * @return FormNode
	 */
	public function getParent()
	{
		return $this->parent;
	}

	/**
	 * Returns whether or not the form is in ajax mode. And thus should generate an additional error element with each element to load the errors in.
	 *
	 * @return bool
	 */
	protected function inAJAXMode() {
		if( $this instanceof Form ) {
			return $this->getProperty('ajax_mode');
		} else {
			return $this->parent->inAJAXMode();
		}
	}


	public function getFormName() {
		if( !$this->parent instanceof Form ) {
			return $this->parent->getFormName();
		} else {
			return $this->parent->getProperty('name');
		}
	}

	/**
	 * Removes this child from its parent, without a parent it will not be rendered.
	 *
	 */
	public function removeFromParent( ) {
		if( $this->parent == NULL ) {
			throw new FormException( "This node does not have a parent" );
		}

		$this->parent->removeChild( $this );
	}

	/**
	 * Validates the form node.
	 *
	 * @return boolean
	 */
	public abstract function isValid();

	public abstract function compareTo( FormNode $fn );

	public function getErrorMessage() {
		return $this->errorMessage;
	}

	/**
	 * The HTML result of the form node.
	 *
	 * @return String
	 */
	public abstract function __toString( );
}

?>